﻿using DZParallelLib.DZImage;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;

namespace DZParallelLib.Test.DZImage
{
    [TestClass]
    public class DZImageBaseTest
    {
        private class MyImage : DZImageBase
        {

            public MyImage(ulong x, ulong y, uint numberLevels = 11)
            {
                Width = x;
                Height = y;
                NumberOfLevels = numberLevels;
                TileSize = 256;
                Overlap = 1;
            }
        }

        [TestMethod]
        public void TestMaxSize()
        {
            var i = new MyImage(10, 100);
            Assert.AreEqual((ulong)100, i.MaxDimension);
            var i1 = new MyImage(101, 5);
            Assert.AreEqual((ulong)101, i1.MaxDimension);
        }

        [TestMethod]
        public void TestImageSizeCalc()
        {
            var i = new MyImage(696, 472);
            var s1 = i.SizeOfImageInLevel(8);
            Assert.AreEqual(174, s1.Width, "Level 8, x");
            Assert.AreEqual(118, s1.Height, "Level 8, y");

            var s2 = i.SizeOfImageInLevel(9);
            Assert.AreEqual(256 + 92, s2.Width, "Level 9, x"); // overlap may have my actual # wrong here
            Assert.AreEqual(236, s2.Height, "Level 9, y");

            var s3 = i.SizeOfImageInLevel(10);
            Assert.AreEqual(696, s3.Width, "Level 10, x");
            Assert.AreEqual(472, s3.Height, "Level 10, y");
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void TestImageSizeCalcBadLevel()
        {
            var i = new MyImage(696, 472);
            var s1 = i.SizeOfImageInLevel(i.NumberOfLevels);
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void TestImageBestSizeTooBig()
        {
            var dz = new MyImage(696, 472);
            var img = dz.LevelThatContainsSize(5000);
        }

        [TestMethod]
        public void TestImageBestSize256()
        {
            var dz = new MyImage(696, 472);
            var img = dz.LevelThatContainsSize(256);
            Assert.AreEqual((uint)9, img, "Level for 256");
        }

        [TestMethod]
        public void TestImageBestSize1x1()
        {
            var dz = new MyImage(696, 472);
            var lvl = dz.LevelThatContainsSize(1);
            Assert.AreEqual((uint)0, lvl);
        }

        [TestMethod]
        public void TestImageBestFullSize()
        {
            var dz = new MyImage(696, 472);
            var lvl = dz.LevelThatContainsSize(dz.MaxDimension);
            Assert.AreEqual(dz.NumberOfLevels - 1, lvl);
        }

        [TestMethod]
        public void TestImageBestSizeForImageSize()
        {
            var dz = new MyImage(696, 472);
            var lvl = dz.LevelThatContainsSize(dz.MaxDimension);
            Assert.AreEqual(dz.NumberOfLevels - 1, lvl);
        }

        [TestMethod]
        public void TestImageFileSizeNubmers()
        {
            var dz = new MyImage(696, 472);
            var imageDescriptor = dz.ImageDescriptorAtLevel(9);
            Assert.IsNotNull(imageDescriptor, "Main return");
            Assert.IsNotNull(imageDescriptor.Images, "Images");
            var tiles = imageDescriptor.Images.ToArray();
            Assert.AreEqual(2, tiles.Length, "# of images");
            Assert.AreEqual((ulong)0, tiles[0].X, "image 0, x0");
            Assert.AreEqual((ulong)0, tiles[0].Y, "image 0, y0");
            Assert.AreEqual((uint)257, tiles[0].Width, "image 0, width");
            Assert.AreEqual((uint)236, tiles[0].Height, "image 0, height");
            Assert.AreEqual("0_0.png", tiles[0].Name, "image 0, Name");

            // Assume rest are right - this just proves that we called the descriptor
            // ctor correctly. The object tests for that have more detail on various
            // configurations.
        }
    }
}
